#pragma once
#include"comm_log.hpp"
//#include<iostream>
#include <stdarg.h>
#define Info 0
#define Debug 1
#define Warning 2
#define Error 3
#define Fatal 4
#define LEFT_BuFFER_FORMAT "[%s][%d.%d.%d %d:%d:%d]"
#define FILE_NAME "log.txt"
#define FILE_PATH "./Log/"


enum PrintfMethod
{
    Screen,
    OneFile,
    ClassFile
};
class Log
{
public:
    Log()
    {
        printMethod=PrintfMethod::Screen;
    }
    std::string level_to_string(int level)
    {
        switch (level)
        {
        case Info:
            return "Info";
        case Debug:
            return "Debug";
        case Warning:
            return "Warning";
        case Error:
            return "Error";
        case Fatal:
            return "Fatal";
        default:
            break;
        }
    }

    void Enable(PrintfMethod _printfMethod)
    {
        this->printMethod=_printfMethod;
    }
    void logmessage(int level, const char *format, ...)
    {
        char leftBuffer[SIZE];
        time_t t = time(nullptr);
        struct tm *ctime = localtime(&t);
        snprintf(leftBuffer, sizeof(leftBuffer), LEFT_BuFFER_FORMAT, level_to_string(level).c_str(), ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,
                 ctime->tm_hour, ctime->tm_min, ctime->tm_sec);
        char rightBuffer[SIZE];

        va_list s;
        va_start(s, format);
        vsnprintf(rightBuffer, sizeof(rightBuffer), format, s);
        va_end(s);
        char logBuffer[2 * SIZE];
        snprintf(logBuffer, sizeof(logBuffer), "%s %s\n", leftBuffer, rightBuffer);
        std::string logtext = logBuffer;
        printLog(level, logtext);
    }

    void OneFilePrint(const char* _filename,std::string &logtext)
    {
        std::string filename=FILE_PATH;
        filename+=_filename;
        int fd = open(filename.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0666);
        if(fd<0)
        {
            perror("open");
        }
        write(fd, logtext.c_str(), logtext.size());
    }

    void ClassFilePrint(int level, std::string &logtext)
    {
        std::string filename=FILE_NAME;
        filename+=".";
        filename += level_to_string(level).c_str();
        OneFilePrint(filename.c_str(),logtext);
    }

    void printLog(int level, std::string &logtext)
    {
        switch (printMethod)
        {
        case Screen:
            std::cout << logtext;
            break;
        case OneFile:
            OneFilePrint(FILE_NAME,logtext);
            break;
        case ClassFile:
            ClassFilePrint(level, logtext);
            break;
        default:
            break;
        }
    }
    ~Log()
    {
    }

private:
    PrintfMethod printMethod; 
};

Log lg;